//
// Created by kyle on 25-7-15.
//

#include "FrameBuffer.h"

#include <cstdint>
#include <algorithm>
#include <cstring>  // for std::memcpy

bool FrameBuffer::init() {
    // 打开帧缓冲设备
    fd = open("/dev/fb0", O_RDWR);
    if (fd < 0) {
        std::cerr << "无法打开帧缓冲设备: " << std::system_error(errno, std::generic_category()).what() << '\n';
        return false;
    }

    // 获取屏幕信息
    if (ioctl(fd, FBIOGET_VSCREENINFO, &var_info) < 0) {
        std::cerr << "无法获取屏幕信息: " << std::system_error(errno, std::generic_category()).what() << '\n';
        return false;
    }

    // 设置基本信息
    width = var_info.xres;
    height = var_info.yres;
    bpp = var_info.bits_per_pixel;
    bytes_per_pixel = bpp / 8;
    screen_size = width * height * bytes_per_pixel;

    // 内存映射
    map = mmap(nullptr, screen_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED) {
        std::cerr << "无法映射帧缓冲: " << std::system_error(errno, std::generic_category()).what() << '\n';
        return false;
    }

    // 分配后备缓冲区
    back_buffer = malloc(screen_size);
    if (!back_buffer) {
        std::cerr << "无法分配后备缓冲区: " << std::system_error(errno, std::generic_category()).what() << '\n';
        return false;
    }

    std::cout << "屏幕分辨率: " << width << "x" << height
            << ", 色深: " << bpp << "位\n";
    return true;
}

void FrameBuffer::clear_back_buffer(uint8_t r, uint8_t g, uint8_t b) {
    if (!back_buffer) return;

    if (bpp == 16) {
        // 16位色 (RGB565)
        const uint16_t rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
        auto *pixels = static_cast<uint16_t *>(back_buffer);
        std::fill_n(pixels, width * height, rgb565);
    } else if (bpp == 24 || bpp == 32) {
        // 24/32位色 (BGR/BGRA)
        const size_t pixel_count = screen_size / bytes_per_pixel;
        auto *pixels = static_cast<uint8_t *>(back_buffer);

        for (size_t i = 0; i < pixel_count; ++i) {
            const size_t offset = i * bytes_per_pixel;
            pixels[offset] = b; // Blue
            pixels[offset + 1] = g; // Green
            pixels[offset + 2] = r; // Red
            pixels[offset + 3] = 0xFF; // Alpha
        }
    }
}

// 更新屏幕显示
void FrameBuffer::update_screen() {
    memcpy(map, back_buffer, screen_size);
}

void FrameBuffer::write_pixel(int x, int y, uint8_t r, uint8_t g, uint8_t b) {
    const int mirrored_y = height - 1 - y;

    if (x >= 0 && x < width && mirrored_y >= 0 && mirrored_y < height) {
        const size_t pos = (mirrored_y * width + x) * bytes_per_pixel;

        if (bpp == 16) {
            const uint16_t rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
            *reinterpret_cast<uint16_t *>(static_cast<uint8_t *>(back_buffer) + pos) = rgb565;
        } else {
            auto *pixel = static_cast<uint8_t *>(back_buffer) + pos;
            pixel[0] = b;
            pixel[1] = g;
            pixel[2] = r;
            if (bytes_per_pixel == 4) {
                pixel[3] = 0xFF;
            }
        }
    }
}

void FrameBuffer::draw_line(int x0, int y0, int x1, int y1, uint8_t r, uint8_t g, uint8_t b) {
    int dx = abs(x1 - x0);
    int dy = abs(y1 - y0);
    int sx = x0 < x1 ? 1 : -1;
    int sy = y0 < y1 ? 1 : -1;
    int err = dx - dy;

    while (true) {
        write_pixel(x0, y0, r, g, b);
        if (x0 == x1 && y0 == y1) break;
        int e2 = 2 * err;
        if (e2 > -dy) {
            err -= dy;
            x0 += sx;
        }
        if (e2 < dx) {
            err += dx;
            y0 += sy;
        }
    }
}

void FrameBuffer::draw_circle(int x0, int y0, int radius, uint8_t r, uint8_t g, uint8_t b) {
    int x = radius;
    int y = 0;
    int err = 0;

    while (x >= y) {
        write_pixel(x0 + x, y0 + y, r, g, b); // 第一象限
        write_pixel(x0 + y, y0 + x, r, g, b); // 第一象限
        write_pixel(x0 - y, y0 + x, r, g, b); // 第二象限
        write_pixel(x0 - x, y0 + y, r, g, b); // 第二象限
        write_pixel(x0 - x, y0 - y, r, g, b); // 第三象限
        write_pixel(x0 - y, y0 - x, r, g, b); // 第三象限 (之前缺少的点)
        write_pixel(x0 + y, y0 - x, r, g, b); // 第四象限
        write_pixel(x0 + x, y0 - y, r, g, b); // 第四象限

        if (err <= 0) {
            y += 1;
            err += 2 * y + 1;
        }
        if (err > 0) {
            x -= 1;
            err -= 2 * x + 1;
        }
    }
}

// 绘制矩形边框
void FrameBuffer::draw_rect(int x, int y, int w, int h, uint8_t r, uint8_t g, uint8_t b) {
    // 绘制四条边
    draw_line(x, y, x + w, y, r, g, b); // 上边
    draw_line(x, y + h, x + w, y + h, r, g, b); // 下边
    draw_line(x, y, x, y + h, r, g, b); // 左边
    draw_line(x + w, y, x + w, y + h, r, g, b); // 右边
}

// 填充矩形
void FrameBuffer::fill_rect(int x, int y, int w, int h, uint8_t r, uint8_t g, uint8_t b) {
    // 确保矩形在屏幕范围内
    if (x < 0) {
        w += x;
        x = 0;
    }
    if (y < 0) {
        h += y;
        y = 0;
    }
    if (x + w > width) w = width - x;
    if (y + h > height) h = height - y;

    if (w <= 0 || h <= 0) return; // 无效尺寸

    // 优化：直接操作后备缓冲区
    const int mirrored_y = height - 1 - y;
    const int bytes_per_line = w * bytes_per_pixel;

    if (bpp == 16) {
        const uint16_t rgb565 = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
        auto *buffer = static_cast<uint16_t *>(back_buffer);

        for (int row = 0; row < h; ++row) {
            uint16_t *line_start = buffer + ((mirrored_y - row) * width + x);
            std::fill_n(line_start, w, rgb565);
        }
    } else {
        auto *buffer = static_cast<uint8_t *>(back_buffer);

        for (int row = 0; row < h; ++row) {
            uint8_t *line_start = buffer + ((mirrored_y - row) * width + x) * bytes_per_pixel;

            for (int col = 0; col < w; ++col) {
                const size_t offset = col * bytes_per_pixel;
                line_start[offset] = b;
                line_start[offset + 1] = g;
                line_start[offset + 2] = r;
                if (bytes_per_pixel == 4) {
                    line_start[offset + 3] = 0xFF;
                }
            }
        }
    }
}

// 填充四分之一圆 (辅助函数)
void FrameBuffer::fill_circle_quarter(int x0, int y0, int radius,
                       uint8_t r, uint8_t g, uint8_t b, int quadrant) {
    int x = radius;
    int y = 0;
    int err = 0;

    while (x >= y) {
        switch (quadrant) {
            case 1: // 左上
                draw_line(x0 - x, y0 - y, x0, y0 - y, r, g, b);
                draw_line(x0 - y, y0 - x, x0, y0 - x, r, g, b);
                break;
            case 2: // 右上
                draw_line(x0, y0 - y, x0 + x, y0 - y, r, g, b);
                draw_line(x0, y0 - x, x0 + y, y0 - x, r, g, b);
                break;
            case 3: // 右下
                draw_line(x0, y0 + y, x0 + x, y0 + y, r, g, b);
                draw_line(x0, y0 + x, x0 + y, y0 + x, r, g, b);
                break;
            case 4: // 左下
                draw_line(x0 - x, y0 + y, x0, y0 + y, r, g, b);
                draw_line(x0 - y, y0 + x, x0, y0 + x, r, g, b);
                break;
        }

        if (err <= 0) {
            y += 1;
            err += 2*y + 1;
        }
        if (err > 0) {
            x -= 1;
            err -= 2*x + 1;
        }
    }
}

// 圆角矩形
void FrameBuffer::draw_rounded_rect(int x, int y, int w, int h, int radius,
                                    uint8_t r, uint8_t g, uint8_t b) {
    // 参数检查
    if (radius <= 0) {
        draw_rect(x, y, w, h, r, g, b);
        return;
    }

    radius = std::min(radius, std::min(w, h) / 2); // 确保半径不超过短边的一半

    // 绘制四个角
    draw_circle_quarter(x + radius, y + radius, radius, r, g, b, 1); // 左上
    draw_circle_quarter(x + w - radius, y + radius, radius, r, g, b, 2); // 右上
    draw_circle_quarter(x + w - radius, y + h - radius, radius, r, g, b, 3); // 右下
    draw_circle_quarter(x + radius, y + h - radius, radius, r, g, b, 4); // 左下

    // 填充四个角的四分之一圆
    fill_circle_quarter(x + radius,     y + radius,     radius, r, g, b, 1); // 左上
    fill_circle_quarter(x + w - radius, y + radius,     radius, r, g, b, 2); // 右上
    fill_circle_quarter(x + w - radius, y + h - radius, radius, r, g, b, 3); // 右下
    fill_circle_quarter(x + radius,     y + h - radius, radius, r, g, b, 4); // 左下

    // 绘制四条边
    fill_rect(x + radius, y, w - 2 * radius, radius, r, g, b); // 上边
    fill_rect(x + radius, y + h - radius, w - 2 * radius, radius, r, g, b); // 下边
    fill_rect(x, y + radius, radius, h - 2 * radius, r, g, b); // 左边
    fill_rect(x + w - radius, y + radius, radius, h - 2 * radius, r, g, b); // 右边
}

// 渐变填充矩形
void FrameBuffer::fill_rect_gradient(int x, int y, int w, int h,
                                     uint8_t r1, uint8_t g1, uint8_t b1,
                                     uint8_t r2, uint8_t g2, uint8_t b2,
                                     bool horizontal) {
    // 边界检查
    if (x < 0) {
        w += x;
        x = 0;
    }
    if (y < 0) {
        h += y;
        y = 0;
    }
    if (x + w > width) w = width - x;
    if (y + h > height) h = height - y;
    if (w <= 0 || h <= 0) return;

    const int mirrored_y = height - 1 - y;

    if (horizontal) {
        // 水平渐变
        for (int col = 0; col < w; ++col) {
            float ratio = static_cast<float>(col) / (w - 1);
            uint8_t r = static_cast<uint8_t>(r1 + (r2 - r1) * ratio);
            uint8_t g = static_cast<uint8_t>(g1 + (g2 - g1) * ratio);
            uint8_t b = static_cast<uint8_t>(b1 + (b2 - b1) * ratio);

            draw_line(x + col, y, x + col, y + h - 1, r, g, b);
        }
    } else {
        // 垂直渐变
        for (int row = 0; row < h; ++row) {
            float ratio = static_cast<float>(row) / (h - 1);
            uint8_t r = static_cast<uint8_t>(r1 + (r2 - r1) * ratio);
            uint8_t g = static_cast<uint8_t>(g1 + (g2 - g1) * ratio);
            uint8_t b = static_cast<uint8_t>(b1 + (b2 - b1) * ratio);

            draw_line(x, y + row, x + w - 1, y + row, r, g, b);
        }
    }
}

// 带边框的填充矩形
void FrameBuffer::fill_rect_with_border(int x, int y, int w, int h,
                                        uint8_t fill_r, uint8_t fill_g, uint8_t fill_b,
                                        uint8_t border_r, uint8_t border_g, uint8_t border_b,
                                        int border_width) {
    // 绘制边框
    fill_rect(x, y, w, border_width, border_r, border_g, border_b); // 上边框
    fill_rect(x, y + h - border_width, w, border_width, border_r, border_g, border_b); // 下边框
    fill_rect(x, y + border_width, border_width, h - 2 * border_width, border_r, border_g, border_b); // 左边框
    fill_rect(x + w - border_width, y + border_width, border_width, h - 2 * border_width, border_r, border_g,
              border_b); // 右边框

    // 填充内部
    if (w > 2 * border_width && h > 2 * border_width) {
        fill_rect(x + border_width, y + border_width,
                  w - 2 * border_width, h - 2 * border_width,
                  fill_r, fill_g, fill_b);
    }
}

// 绘制四分之一圆 (辅助函数)
void FrameBuffer::draw_circle_quarter(int x0, int y0, int radius,
                                      uint8_t r, uint8_t g, uint8_t b, int quadrant) {
    int x = radius;
    int y = 0;
    int err = 0;

    while (x >= y) {
        switch (quadrant) {
            case 1: // 左上
                write_pixel(x0 - y, y0 - x, r, g, b);
                write_pixel(x0 - x, y0 - y, r, g, b);
                break;
            case 2: // 右上
                write_pixel(x0 + y, y0 - x, r, g, b);
                write_pixel(x0 + x, y0 - y, r, g, b);
                break;
            case 3: // 右下
                write_pixel(x0 + x, y0 + y, r, g, b);
                write_pixel(x0 + y, y0 + x, r, g, b);
                break;
            case 4: // 左下
                write_pixel(x0 - x, y0 + y, r, g, b);
                write_pixel(x0 - y, y0 + x, r, g, b);
                break;
        }

        if (err <= 0) {
            y += 1;
            err += 2 * y + 1;
        }
        if (err > 0) {
            x -= 1;
            err -= 2 * x + 1;
        }
    }
}
